<!--
 * hi-number-step - 步进器
 *
 * @author 济南晨霜信息技术有限公司
 * @mobile 18560000860 / 18754137913
 -->
<template>
    <view class="hi-number-step" :class="_classes" :style="_styles">
        <!-- 减 -->
        <view
            class="hi-number-step__icon hi-number-step__icon--minus"
            :hover-class="hover"
            :class="{ 'hi-disabled hi-number-step__icon--disabled': _disabledMinus }"
            v-if="showMinus"
        >
            <hi-icon :name="minusIcon" @click="onMinus"></hi-icon>
        </view>

        <!-- 值 -->
        <input
            class="hi-number-step__input"
            type="digit"
            v-model="inputValue"
            @input="onInput"
            @focus="_emits('focus')"
            @blur="_emits('blur')"
            @confirm="_emits('confirm')"
            @keyboardheightchange="_emits('keyboardheightchange')"
            :disabled="disabledInput"
            :placeholder="placeholder"
            :placeholder-class="placeholderClass"
            :placeholder-style="placeholderStyle"
            :cursor-spacing="cursorSpacing"
            :focus="focus"
            :confirm-hold="confirmHold"
            :cursor="cursor"
            :cursor-color="cursorColor"
            :selection-start="selectionStart"
            :selection-end="selectionEnd"
            :adjust-position="adjustPosition"
            :auto-blur="autoBlur"
            :ignoreCompositionEvent="ignoreCompositionEvent"
            :always-embed="alwaysEmbed"
            :hold-keyboard="holdKeyboard"
            :safe-password-cert-path="safePasswordCertPath"
            :safe-password-length="safePasswordLength"
            :safe-password-time-stamp="safePasswordTimeStamp"
            :safe-password-nonce="safePasswordNonce"
            :safe-password-salt="safePasswordSalt"
            :safe-password-custom-hash="safePasswordCustomHash"
            :random-number="randomNumber"
            :controlled="controlled"
            :always-system="alwaysSystem"
            :inputmode="inputmode"
            :maxlength="maxlength"
        />

        <!-- 加 -->
        <view
            class="hi-number-step__icon hi-number-step__icon--plus"
            :hover-class="hover"
            :class="{ 'hi-disabled hi-number-step__icon--disabled': _disabledPlus }"
            v-if="showPlus"
        >
            <hi-icon :name="plusIcon" @click="onPlus"></hi-icon>
        </view>
    </view>
</template>

<!-- 由于 HbuilderX 不支持 defineOptions() 写法，故只能在此处进行配置 -->
<script>
    export default { options: uni?.$hi?.config?.componentsOptions || {} };
</script>

<script setup>
    import { ref, computed, watch, nextTick } from "vue";
    import inputProps from "../../props/input";
    import props from "./props.js";

    // 组件属性
    const _props = defineProps({
        ...inputProps,
        ...props
    });

    // 组件事件
    const _emits = defineEmits([
        "change",
        "asyncChange",
        "update:modelValue",
        "plusClick",
        "minusClick",
        "input",
        "focus",
        "blur",
        "confirm",
        "keyboardheightchange"
    ]);

    // 组件类名
    const _classes = computed(() => {
        const classes = [];

        // 是否禁用全部？
        if (_props.disabled) classes.push(`hi-disabled hi-number-step--disabled`);

        // 边框
        if (_props.border) classes.push(`hi-number-step--border`);

        return classes;
    });

    // 组件样式
    const _styles = computed(() => {
        const styles = [];

        // 宽
        if (_props.width) styles.push(`--hi-number-step-width: ${_props.width};`);

        // 高
        if (_props.height) styles.push(`--hi-number-step-height: ${_props.height};`);

        // 圆角
        if (_props.radius) styles.push(`--hi-number-step-border-radius: ${_props.radius};`);

        // 文字颜色
        if (_props.color) styles.push(`--hi-number-step-color: ${_props.color};`);

        // 文字大小
        if (_props.fontSize) styles.push(`--hi-number-step-font-size: ${_props.fontSize};`);

        // 背景
        if (_props.bg) styles.push(`--hi-number-step-background: ${_props.bg};`);

        // 边框颜色
        if (_props.borderColor) styles.push(`--hi-number-step-border-color: ${_props.borderColor};`);

        // 边框聚焦时的颜色
        if (_props.focusBorderColor) styles.push(`--hi-number-step-focus-border-color: ${_props.focusBorderColor}`);

        // 边框粗细
        if (_props.borderWidth) styles.push(`--hi-number-step-border-width: ${_props.borderWidth}px;`);

        // 输入框文本对齐方式
        if (_props.align) styles.push(`--hi-number-step-input-text-align: ${_props.align};`);

        // 图标颜色
        if (_props.iconColor) styles.push(`--hi-number-step-icon-color: ${_props.iconColor}`);

        // 图标大小
        if (_props.iconSize) styles.push(`--hi-number-step-icon-font-size: ${_props.iconSize}`);

        // 图标宽度
        if (_props.iconWidth) styles.push(`--hi-number-step-icon-width: ${_props.iconWidth}`);

        // 图标背景
        if (_props.iconBg) styles.push(`--hi-number-step-icon-background: ${_props.iconBg}`);

        // 加号图标颜色
        if (_props.plusColor) styles.push(`--hi-number-step-plus-icon-color: ${_props.plusColor}`);

        // 加号图标背景
        if (_props.plusBg) styles.push(`--hi-number-step-plus-icon-background: ${_props.plusBg}`);

        // 减号图标颜色
        if (_props.minusColor) styles.push(`--hi-number-step-minus-icon-color: ${_props.minusColor}`);

        // 减号图标背景
        if (_props.minusBg) styles.push(`--hi-number-step-minus-icon-background: ${_props.minusBg}`);

        // 输入框宽度
        if (_props.inputWidth) styles.push(`--hi-number-step-input-width: ${_props.inputWidth}`);

        // 输入框背景
        if (_props.inputBg) styles.push(`--hi-number-step-input-background: ${_props.inputBg}`);

        return styles;
    });

    // 输入框的值
    const inputValue = ref(_props.modelValue);

    // 是否禁用减号按钮
    const _disabledMinus = computed(() => {
        return _props.disabled || _props.disabledMinus || _props.modelValue <= _props.min;
    });

    // 是否禁用加号按钮
    const _disabledPlus = computed(() => {
        return _props.disabled || _props.disabledPlus || _props.modelValue >= _props.max;
    });

    // 同步更新视图的值
    watch(
        () => _props.modelValue,
        (value) => {
            updateInputValue();
        },
        { immediate: true }
    );

    /**
     * 加
     */
    function onPlus() {
        _emits("plusClick");

        // 开启了异步变更
        if (_props.async) {
            _emits("asyncChange", _props.modelValue + _props.step);
            return;
        }

        // 当前值加上步进值超出最大值
        if (_props.modelValue + _props.step > _props.max) {
            _emits("update:modelValue", _props.max);
            _emits("change", _props.max);
            return;
        }

        // 当前值加上步进值未超出最大值
        _emits("update:modelValue", _props.modelValue + _props.step);
        _emits("change", _props.modelValue + _props.step);
    }

    /**
     * 减
     */
    function onMinus() {
        _emits("minusClick");

        // 开启了异步变更
        if (_props.async) {
            _emits("asyncChange", _props.modelValue - _props.step);
            return;
        }

        // 当前值减去步进值小于最小值
        if (_props.modelValue - _props.step < _props.min) {
            _emits("update:modelValue", _props.min);
            _emits("change", _props.min);
            return;
        }

        // 当前值减去步进值未小于最小值
        _emits("update:modelValue", _props.modelValue - _props.step);
        _emits("change", _props.modelValue - _props.step);
    }

    /**
     * 输入框输入事件
     * @param {Event} event event.detail.value 输入的值
     */
    function onInput(event) {
        _emits("input", event);

        // 输入的值
        const value = Number(event.detail.value);

        // 开启了异步变更
        if (_props.async) {
            _emits("asyncChange", value);
            return;
        }

        // 未开启异步变更
        // 判断是否超出范围
        // 超出范围
        if (value > _props.max || value < _props.min) {
            // 更新输入框视图的值
            updateInputValue();
            return;
        }

        // 未超出范围
        _emits("update:modelValue", value);
        _emits("change", value);
    }

    /**
     * 更新输入框视图的值
     */
    function updateInputValue() {
        // uni-app 更新输入框视图的值需要放到 nextTick 中，并且确保更新还得放到 setTimeout 中，晕~~~
        nextTick(() => {
            setTimeout(() => {
                inputValue.value = _props.modelValue;
            }, 10);
        });
    }
</script>

<style lang="scss" scoped>
    .hi-number-step {
        transition: var(--hi-number-step-transition, border 0.2s);
        display: var(--hi-number-step-display, flex);
        height: var(--hi-number-step-height, 2em);
        border: var(--hi-number-step-border-width, 0) var(--hi-number-step-border-style, solid) var(--hi-number-step-border-color, var(--hi-border-color));
        overflow: var(--hi-number-step-overflow, hidden);
        align-items: var(--hi-number-step-align-items, stretch);
        width: var(--hi-number-step-width, auto);
        border-radius: var(--hi-number-step-border-radius, 0);
        color: var(--hi-number-step-color, inherit);
        font-size: var(--hi-number-step-font-size, inherit);
        background: var(--hi-number-step-background, var(--hi-background-default));

        &__icon {
            color: var(--hi-number-step-icon-color, inherit);
            font-size: var(--hi-number-step-icon-font-size, inherit);
            background: var(--hi-number-step-icon-background, transparent);
            flex-shrink: var(--hi-number-step-icon-flex-shrink, 0);
            display: var(--hi-number-step-icon-display, flex);
            align-items: var(--hi-number-step-icon-align-items, center);
            justify-content: var(--hi-number-step-icon-justify-content, center);
            width: var(--hi-number-step-icon-width, 2em);

            &--plus {
                color: var(--hi-number-step-plus-icon-color, var(--hi-number-step-icon-color, inherit));
                background: var(--hi-number-step-plus-icon-background, var(--hi-number-step-icon-background, transparent));
            }

            &--minus {
                color: var(--hi-number-step-minus-icon-color, var(--hi-number-step-icon-color, inherit));
                background: var(--hi-number-step-minus-icon-background, var(--hi-number-step-icon-background, transparent));
            }
        }

        &__input {
            width: var(--hi-number-step-input-width, 4em);
            text-align: var(--hi-number-step-input-text-align, center);
            border-color: var(--hi-number-step-border-color, var(--hi-border-color));
            border-style: var(--hi-number-step-border-style, solid);
            border-left-width: var(--hi-number-step-input-border-left-width, 0);
            border-right-width: var(--hi-number-step-input-border-right-width, 0);
            border-top-width: var(--hi-number-step-input-border-top-width, 0);
            border-bottom-width: var(--hi-number-step-input-border-bottom-width, 0);
            height: 100%;
            flex: var(--hi-number-step-input-flex, 1);
            font-size: var(--hi-number-step-input-font-size, inherit);
            color: var(--hi-number-step-input-color, inherit);
            transition: var(--hi-number-step-transition, border 0.2s);
            background: var(--hi-number-step-input-background, transparent);
        }

        &--border {
            border-width: var(--hi-number-step-border-width, 1px);

            .hi-number-step__input {
                border-left-width: var(--hi-number-step-input-border-left-width, 1px);
                border-right-width: var(--hi-number-step-input-border-right-width, 1px);
            }
        }

        &:focus-within {
            border-color: var(--hi-number-step-focus-border-color, var(--hi-number-step-border-color, var(--hi-border-color)));

            .hi-number-step__input {
                border-color: var(--hi-number-step-focus-border-color, var(--hi-number-step-border-color, var(--hi-border-color)));
            }
        }
    }
</style>
